Repository navigation
Conversation
Signed-off-by: ChengLong GU <88359731+gcl-coder@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=max
REQUEST_CHANGES:1 个 P2。默认预算可打断已经登记的临时 worktree,但异常路径没有撤销登记;成功重试后仍留下失效记录。
动机 / Motivation
维护多条已评审分支的开发者需要整合当前 source heads,同时在 Git helper 卡住时得到明确失败。旧同步可能无限等待;新实现让单次 Git 操作超时退出,正常情况下仍生成候选、发布本地整合分支并读回回执。可验证的目标是有界失败后仍能安全继续;本 PR 不改变 plan、分支顺序、source refs 或远端/PR 权限,临时 worktree 清理仍是这个目标的一部分。目前尚缺超时后撤销本次 candidate 登记的恢复路径。
改动思路 / Approach
唯一 Git 入口 _git 保持既有文本和错误处理,并将 communicate 等待限制到每次 10 秒;共享 process_runtime.retire_owned_process 负责已拥有进程组和管道的有界回收。这是既有 Python Git adapter 的 IO 边界,不是新增的 Core 决策能力。与 change_quality.scope、并行 #8362 相比,进程回收 owner 已复用,文本/bytes 与能力异常不必强行合成新框架。
但这里的 _git 同时执行 fetch、merge、worktree add/remove、reset 和 update-ref,并不都是读取。当前切片必须把新超时接入已有写操作的失败清理;仅杀进程不等于撤销 Git 已完成的登记。无需扩大成新事务系统:在既有 _build_candidate 里补本次 candidate 的有界清理并保留原异常,即可完成这个切片。不修改 plan schema、source refs、远端或 PR 权限。
具体改动 / Changes
全 PR 为 2 文件,+153/-6;生产文件 +62/-6,新增测试 91 行。规范依据 loopx/capabilities/integration_branch/README.md,不可变版本 c63a8f9cfc023ff22f39db5cb8b734da7653e83d,原文未被本 PR 改写。configure 的 preview-first 和 ignored plan、boundary 的不 push/不改 source branch 均通过真实 CLI;preview-and-sync 的临时 worktree 清理在下面反例中未满足,需修复后重验。
关键代码讲解
_gitL47 将每次 Git 操作放入独立 POSIX session,正常返回维持 UTF-8 replace 和原非零诊断。L73–79 的新 TimeoutExpired 分支回收进程后立即抛 IntegrationBranchError;它也可能中断已有写操作,不能只按读取失败理解。_retire_owned_readL30 复用共享回收函数,不把清理异常替换成成功结果。这个边界能限制等待,但并不知道 Git 是否已在 common dir 中登记 worktree。_build_candidateL605 先执行 worktree add,直到其返回后才把 added 设为 True。真实 post-checkout hook 是登记完成之后运行的;此时被新预算中断,finally 看到 added=False,跳过 worktree remove,却删除临时目录,留下 .git/worktrees 中指向不存在目录的条目。
对主干的风险 / Risks
[P2] 超时后清理本次 worktree 登记
独立真实 Git/公开 CLI 反例:建立 main、feature-a 和 ignored plan,先同步;推进 feature-a,再安装内容为 #!/bin/sh 加 sleep 11.5 的 .git/hooks/post-checkout,执行 loopx --format json integration-branch sync --repo-path <fixture> --execute,保留默认 10 秒。不可变 base 约 13.57 秒成功、0 个失效 worktree;本 head 约 11.54 秒返回 rc=2/invalid_state 和 worktree add 超时,git worktree list --porcelain 多出 1 个 prunable gitdir file points to non-existent location 条目。移除 hook 后重试同步成功,该条目依然存在。周期同步每次遭遇同样超时都会累积本能力自己的失效登记,不能由“已退出”或“重试成功”证明资源已收回。
最小修复:让 _build_candidate 在 worktree add 已产生部分效果而抛错时,也撤销本次 candidate 登记;清理即使出错也要执行目录收尾并保留原超时。只处理本次拥有的路径,不全局 prune 其他工作。新增真实 Git 的慢 post-checkout 回归,断言超时后 worktree 清单、临时目录、integration branch 和 last_sync 均符合预期,再验证解除故障后的成功与重复执行。
PASS:77 tests,1 skipped;新 3 条预算测试和原 integration、共享 process runtime 测试均通过。独立 CLI 的 configure preview/execute/replay、drift status、sync preview/execute/replay、in-sync status 和越界 plan 拒绝,共 9 项的完整 JSON/退出码在 base/head 相同;上面的写中断反例 FAIL,现有 fake-git 测试没有覆盖登记后 hook 阻塞。
本地 standard premerge 的 6 项直接检查和 2 项 catalog 检查通过。另行执行的 maintainability ratchet 仍 FAIL:Lark private_conversations.py 的 module_metric_budget;同一命令在不可变 base 与 head 的完整 450 字节输出相同,相关规则、配置及模块未改,原阈值保留。它是独立告警,不能掩盖本次反例。未查询或等待远端 CI。
原生 Windows 未运行,不能把 POSIX 或模拟分支当作 Windows 资格。10 秒按每次调用重新分配,另有有界清理时间;不是整条 sync 的总 deadline。默认仍不刷新 remote、preview 不发布 integration ref,stdin 从继承改为 DEVNULL 的行为也应作为自动化非交互边界明确保留。
我的整体评价 / Verdict
long_horizon:regression,重复超时可累积失效 worktree 登记;user_experience:regression,返回错误和成功重试都没有揭示或清掉遗留资源。当前必要修复是既有 candidate 生命周期内的清理,不是强制改写到 TypeScript 或增加全局状态。此处未改 rendered presentation,已检查 CLI/plan/Git 生命周期,visual_review 为 not_applicable,未验证范围是原生 Windows、生产采用与长期完整成本。共享词汇、actor 与权限未扩张,架构和代码量基本适配;正确方向及绿色单测仍不能覆盖已复现的生命周期缺口。修复后需在新精确 head 重跑完整 PR 及上述真实反例。
English verdict: REQUEST_CHANGES — timed-out worktree creation leaves a stale registration after recovery.
| try: | ||
| stdout, stderr = process.communicate(timeout=GIT_READ_TIMEOUT_SECONDS) | ||
| except subprocess.TimeoutExpired: | ||
| _retire_owned_read(process) |
There was a problem hiding this comment.
[P2] 超时后仍需撤销已产生的 worktree 登记。真实 post-checkout hook 等待11.5秒时,worktree add 已在 common dir 登记,随后被默认10秒预算中断;_build_candidate 尚未执行 added=True,finally 跳过 worktree remove,却删除临时目录。本 head 返回 rc2 后遗留一个 prunable 登记,移除 hook 并成功重试后仍存在;相同 base 成功且没有遗留。请让既有 candidate owner 在 add 部分完成后失败时也清理本次登记,保持原超时并在清理失败时仍收尾目录,避免全局 prune 无关工作。请补真实 Git 回归覆盖超时后的清单、目录、branch/receipt 不变及恢复。
Signed-off-by: ChengLong GU <88359731+gcl-coder@users.noreply.github.com>
|
这条 P2 成立,已经按最小范围修了。 根因确认: 改动:
本地: 未覆盖: |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=max
REQUEST_CHANGES:2 个 P2。慢 hook 的旧登记泄漏已修复,但异常清理仍会遗留目录,fallback 还会清理不属于本次操作的 worktree。
精确 head:2f2222868ba4c720d0cbd11dd8d5e59aad3d1391
动机 / Motivation
整合多条 source 分支的开发者需要在 Git helper 卡住时得到可恢复的同步结果。旧同步无限等待,修订给每次 Git 操作设置预算,并试图在超时后清理本次候选 worktree。慢 hook 的旧泄漏已修复,但清理失败与范围反例仍未通过。本 PR 不改变 source refs、远端或 PR 权限;临时资源完整收尾属于当前切片。当前仍缺清理自身失败后收尾、保留原错误和无关登记的保证。
改动思路 / Approach
入口 _git 为既有 integration-branch 的每次 Git 调用设置 10 秒 communicate 等待,并复用 process_runtime.retire_owned_process 回收已拥有进程。这个入口也执行 worktree add/remove、merge 和 update-ref,因此必须处理被中断的部分写入,不能把所有调用按纯读取理解。修订把 added 改成 add 前置的 attempted,能覆盖登记完成但 post-checkout 未结束的情况;remove 的双 --force 可以清理本次锁定 candidate。
原方案不设时限会长期占住同步,单用 timeout 又会留下后代;共享 runtime 加本地 adapter 是合理的较小选择。需要修复的是同一 owner 内的失败收尾和范围,不能用全局 prune 代替本次资源清理。没有必要引入事务框架、新状态或强制语言迁移。
Python 仍是现有 Git provider IO;共享 runtime 负责进程回收,没有新增 Core 决策 owner。当前切片必须在原 owner 内保持原错误、完整清理本次资源并保护无关工作。
具体改动 / Changes
全 PR 是 2 文件,+249/-10;core.py +107/-10,预算测试新增 142 行。本次重新审查整个 base→head,同时单独核对 7a30dba→本 head 的 attempted、remove 和 prune 修订;没有继承上次结论。新增真实 hook 测试只覆盖 remove 正常完成,未覆盖 remove 自身超时及无关失联 worktree。
关键代码讲解
- _git L47 保留 UTF-8、原 check 处理和共享回收,新增每次 10 秒等待;check=False 只允许非零退出,不抑制 timeout/OSError,且这不是整条 sync 的总 deadline。
- _build_candidate L630 在 add 前记录尝试,并在 finally remove;正常超时现在不留登记。但 L680 的清理异常会提前跳出 finally,使 L690 的目录删除无法执行,且覆盖更早的 add 错误。
- _prune_missing_candidate L605 用路径判断是否进入 fallback,但 L626 运行的 Git prune 没有单 worktree 参数。这是条件局部、效果全局,实际删除范围没有被前面的判断限制。
规范依据是不可变 base c63a8f9cfc023ff22f39db5cb8b734da7653e83d 中的 loopx/capabilities/integration_branch/README.md,在读 diff 前已核对,PR 未改其验收边界。configure/boundary 的 preview-first、本地 plan、不 push/source rewrite 均保持;preview-and-sync 的临时资源清理仍未满足。 repository-experience 的既有有用切片建议在当前 head 采用:按用户能够完成的同步/收据任务判断,不把测试数、字段或父路线图完成当作验收。
对主干的风险 / Risks
PASS:78 tests,1 skipped;integration、预算和共享 process runtime 套件。公开 CLI 的 configure preview/execute/replay、drift status、sync preview/execute/replay、in-sync status 和越界 plan 拒绝,共 9 项完整规范化 JSON 与退出码在 base/head 相同。默认 10 秒、真实 post-checkout sleep11.5 反例:base 约13.55秒成功,本 head 约11.01秒明确拒绝且0个失效登记,integration ref 未变;解除 hook 后成功。恢复操作的 updated 标记不同是前置成功/失败状态不同,最终 integration/last_sync 相同,不将其规范成假同值。
[P2] 清理自身超时仍须完成收尾
真实公开 sync + native post-checkout sleep2,PATH wrapper 只把 worktree remove 延迟2秒,测试内每次预算0.4秒。base 完成、无候选遗留;本 head 返回 worktree remove 超时,原 add 超时被覆盖,candidate 目录和登记都仍存在。check=False 无法避免 _git 自己抛错。请在已有 candidate owner 中用嵌套 finally 保证目录收尾,保留原异常/取消,同时如实报告登记清理未确认;新增 remove/list 也失败的真实边界回归。
[P2] 不得为一个候选全局 prune
隔离真实仓库保留一个目录暂时移走、登记已超过两分钟的无关 worktree;native hook 仅删本次 candidate,shell wrapper 拒绝 remove,其余全部交给真实 Git,测试预算1.2秒。base 保留无关登记,本 head 确实执行 worktree prune --expire now 后将它删除。没有 mock 替代清理结果。最初0.4秒 Python wrapper 的探针未能稳定到达目标分支,保留为无效/未触发观察;改用 shell、明确旧登记后复现。请只撤销本次登记,并断言离线/不可达的其他 worktree 在失败和恢复后均保留。
standard premerge 的6项直接检查通过;catalog/risk 合计2项按原生 gate 通过,另有 maintainability advisory FAIL。后者在相同 base/head 的完整450字节输出相同,Lark 模块、规则和配置未改,原阈值保留;它不解释本次已复现的回归。未查询、轮询或等待远端 CI。原生 Windows 未运行;POSIX 模拟分支不能认证原生 Windows。所有写入仅在隔离仓库/夹具;没有用户 Host 安装、付费模型或生产采用测试。
我的整体评价 / Verdict
long_horizon:regression;清理可能遗留本次资源或删除无关登记,反复同步会增加恢复成本。 user_experience:regression;正常流程不增加确认轮次,但失败路径仍不能可靠继续,需要在现有 owner 内修复。架构切片和代码量基本适配,维持 proportionate;方向正确与部分修复通过不能覆盖当前 P2。当前 reviewed prior-head 的慢 hook 泄漏已通过本轮独立重跑,不撤销历史失败,也不自动解决旧讨论。
此处没有 rendered presentation 改动;已检查公开 CLI、provider 和持久收据/清理路径,visual_review 为 not_applicable。未验证范围:原生 Windows、生产 Host 采用、长期完整成本。没有新增共享 enum、actor 或权限;Git-specific 诊断留在 Git provider,没有把产品或 benchmark 条件塞入通用义务。安全范围不变:review 不是 merge、安装或执行模型的授权。修复后需对新精确 head 重跑完整 PR 和上述真实边界反例。
English verdict: REQUEST_CHANGES — 2f22228; two reproducible cleanup defects remain after the original hook leak was fixed.
| # Remove this candidate's own registration while its directory | ||
| # still exists; a cleanup failure must not replace the timeout or | ||
| # cancellation that ended the attempt. | ||
| _git( |
There was a problem hiding this comment.
[P2] 清理命令也会超时,check=False 不会抑制 _git 的 IntegrationBranchError。真实公开 sync 中,post-checkout 等待2秒,wrapper 仅延迟 worktree remove 2秒,测试预算0.4秒:返回的错误变成 remove 超时,原 add 超时被覆盖;L690 的 rmtree 未执行,candidate 目录和登记均留下。请在现有 owner 中用嵌套 finally 保证目录收尾,保留原异常/取消,并如实保留登记回收未确认的状态;补 remove/list 自身失败及恢复的真实 Git 回归。
| if resolved != target: | ||
| continue | ||
| if not candidate.exists(): | ||
| _git(repo, "worktree", "prune", "--expire", "now", check=False) |
There was a problem hiding this comment.
[P2] 前面的候选路径匹配只限制何时进入分支,不能限制 git worktree prune 的效果;此命令没有单路径参数,会删除 common dir 中所有符合条件的失联 worktree 登记。真实公开 sync 夹具中,native hook 只删除本次 candidate,shell wrapper 拒绝 candidate remove;一个目录暂时移走、登记已较旧的无关 worktree 在 base 保留,而本 head 执行这里后将其删除。请只撤销本次拥有的 candidate 登记,避免全局 prune,并回归断言其他离线 worktree 在失败与恢复后仍保留。
…er worktrees Signed-off-by: ChengLong GU <88359731+gcl-coder@users.noreply.github.com>
|
两条 P2 都修了,新 head 需重看。 P2-1 清理命令自身超时。 P2-2 全局 prune。 已删除 覆盖: |
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent | gpt-6.1-sol | OpenAI | runtime_reported | reasoning_effort=max
APPROVE:本 head 未发现阻断项。上轮发现已用当前版本的真实入口重新验证,以下结论覆盖完整 PR。
精确 head:2cb8ca0300948d0a918be3707c98ffe1ed397176
动机 / Motivation
整合多个 source 分支的开发者需要在 Git helper 卡住时结束本次同步,并能安全重试。旧同步可无限等待;直接中断 worktree add 又可能留下部分登记。本 head 将等待限制在每次 Git 调用,并只清理本次候选。真实超时不再遮蔽原错误,候选目录和自身登记得到清理,无关失联登记保留,解除故障后可继续同步。不改动会继续保留已复现的等待或文件身份问题;验证对象是开发者能否完成原任务、看见失败并重试,而不是仅检查 helper 返回或测试数量。本 PR 不增加远端写入、合并、安装、模型执行或额外调用权限;原生 Windows 与生产长期收益不在本地资格内。
改动思路 / Approach
共享 runtime 负责进程生命周期;本能力负责 Git 的文本/错误合同和本次 detached candidate 的退役。新增的本地收尾并未成为第二个 Core 决策 owner。只加 timeout 会留下部分 worktree;全局 prune 又会越过本次范围。当前把这两段在同一 owner 内一起闭合,是可独立验收的较小切片。
Git/文件名/目录清理属于现有 Python provider IO;进程回收复用共享 runtime,资格决策仍归原 typed owner。本切片闭合每次 Git 等待、部分候选收尾和本次资源范围,后续不需要新事务框架。最强反对理由是预算可能拒绝合法慢操作、额外清理需要理解 Git 元数据,以及路径 codec 必须同时守住越界边界;这些成本已由现有 owner 和对应真实反例验证约束。没有新增安装、配置、确认或信息重填轮次。
具体改动 / Changes
本 PR 全量为2文件,+477/-10。另单独核对上一评审 head 到当前 head 的修复:2f222286 的 cleanup timeout/global prune 两项已改为嵌套收尾及候选精确匹配。历史失败保持其原有结论,没有将其重写为通过,也没有继承上次批准趋势。
关键代码讲解
-
_git L47 使用 Popen/communicate,每次等待10秒;timeout 与取消进入共享 retire_owned_process,正常 UTF-8、退出码及 check 语义保留。此入口也执行 merge、fetch、update-ref,所以预算不是只读专用,更不是整条 sync 的总上限。
-
_retire_candidate_worktree L642 把 remove 的非零退出、超时和启动失败留在本地收尾;目录删除放在 finally,原 add 错误继续传播。
-
_unregister_candidate L605 通过 Git common dir 下每个 gitdir 指针匹配本候选的 .git 路径,只删除匹配项,替代没有单路径参数的 global prune。
-
_build_candidate L678 在 add 前标记 attempted,覆盖登记已写但 hook 未结束的状态;finally 无论 add 是否返回都退役本次资源。双重 IO 故障仍可能留下可见的 prunable 登记,不能将它称为清理成功。
规格依据:loopx/capabilities/integration_branch/README.md;spec_revision:c63a8f9cfc023ff22f39db5cb8b734da7653e83d。Configure、Preview-and-sync、Boundary 在本 head 均为 implemented,分别映射到上述现有入口、完整 CLI 正反例和持久状态读回。它们指向原 README 的章节/编号步骤,不新增父级 roadmap 门槛。
对主干的风险 / Risks
PASS:integration 与共享 process runtime 集合81 passed、1 skipped。9项 ordinary configure/status/preview/execute/replay/越界拒绝的完整规范化 JSON 和退出码均与 base 相同。默认10秒、真实 post-checkout sleep11.5:base 约13.63秒完成,head 约11.44秒拒绝,integration ref 未变、无失效登记;解除 hook 后成功。
上轮两项 P2 重新独立验证:实际公开 sync、真实 hook sleep2、shell wrapper 仅延迟或拒绝 remove,测试内每次预算0.8秒。head 返回原 add 超时,candidate 目录消失,worktree 清单与调用前一致;加入一个目录暂时移走且登记已较旧的无关 worktree 后,其登记仍保留。没有 mock 提供这些后置状态。
同时拒绝 remove 和 common-dir 读取时,目录仍删除、原错误保留、plan/ref 不变,但登记不能确认撤销。这个残余如实保留;异常 note 也不会自动成为公开 CLI JSON 字段。正常重试的成功不被当作磁盘/权限失败已自动修复。
原生 standard premerge 的6项直接检查和2项选择检查通过 gate。首次运行因工作树缺 TypeScript 开发依赖失败,已保留失败记录,安装 npm ci --ignore-scripts 后在相同未改 head 重跑通过。另有原 Lark 模块 metric advisory FAIL:当前 base/head 完整450字节输出一致,相关模块、oracle、配置与阈值未变;没有把它改成 PASS。未查询或等待远端 CI。
我的整体评价 / Verdict
long_horizon:improved;真实超时不再遮蔽原错误,候选目录和自身登记得到清理,无关失联登记保留,解除故障后可继续同步。 user_experience:improved;原有入口、关闭/预览态与普通重放不增加操作轮次,失败后由原 caller 继续。这里的改善限定于验证过的本地任务和恢复,不宣称已测得生产 token、费用或长期净收益。
代码规模与已复现问题相称,判为 proportionate;把 candidate 退役集中到本地 helper 并删除 global prune,完成同域简化。Git admin fallback 仍需后续平台兼容回归。没有 rendered presentation 改动;已检查公开 CLI、Git provider 及持久收据/候选清理旅程。未验证范围:原生 Windows、生产 Host 采用、长期完整成本与收益。共享 typed vocabulary、权限和通用义务不变。评审结论与旧 blocking review 的正式状态、readiness 及维护者合并决定分别处理。
English verdict: APPROVE — 2cb8ca0; bounded Git and scoped candidate recovery pass the current whole-PR checks.
动机 / Motivation
repository-change-window与change-quality的 Git 读取已经有预算(#8362、#8169),但整合分支这条路径还没有:loopx/capabilities/integration_branch/core.py的_git()是所有读取的唯一入口,configure_integration_branch、integration_branch_status、sync_integration_branch都经由它执行rev-parse、check-ignore、worktree list、fetch、merge、update-ref等命令,底层是一个没有上限的subprocess.run。仓库卡在陈旧
index.lock、网络挂载或卡住的 fsmonitor helper 上时,这条调用链既不返回也不报错;放在 hook 或自动化里就会把 Git 操作本身一起挂住。改动思路 / Approach
_git()仍是唯一入口,只在这一处加上预算:Popen,用communicate(timeout=GIT_READ_TIMEOUT_SECONDS)等待,预算 10 秒。retire_owned_process,在同一 deadline 内回收这次读取拥有的进程组、关闭未排空的管道;随后抛IntegrationBranchError。check=True时非零退出仍按stderr给出原有的错误细节。与 #8169、#8362 一样,这里只复用既有 owner:Git 读取的接口属于本能力,进程与管道的回收属于共享 runtime。
具体改动 / Changes
_git():从裸subprocess.run改为独立 session 的Popen+ 有界communicate;超时与取消都先回收再抛出/继续传播。_retire_owned_read():只回收本次读取拥有的会话,清理异常不替换本次读取的 timeout 或取消结果。tests/capabilities/test_integration_branch_git_budget.py:新增三条用例——正常读取保留文本与退出码、永不作答的假 git 在预算内拒绝且心跳停止、Git 无法启动时仍抛OSError。对主干的风险 / Risks
tests/capabilities/test_integration_branch.py加新增三条共 18 项全部通过(18 passed)。taskkill与 Job Object 路径由共享 runtime 承担,其行为已在 fix(change-quality): hold every Git read of the scope to one budget #8169 的注入用例中验证,本 PR 沿用同一入口。fetch);这是有意的 fail-closed 边界,调用方会拿到明确错误,而不是无限等待。status/sync的输出结构、CLI 参数或合并权限。我的整体评价 / Verdict
范围限定在一处 Git 入口,复用已验证的共享回收路径,正常结果与错误细节都保持不变。原生 Windows 与最慢读取的取舍仍待评审确认。